package org.streets.eis.component.buttonededit;

import org.apache.wicket.RequestContext;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.markup.ComponentTag;
import org.apache.wicket.markup.MarkupStream;
import org.apache.wicket.markup.html.IHeaderContributor;
import org.apache.wicket.markup.html.IHeaderResponse;
import org.apache.wicket.markup.html.form.AbstractTextComponent;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.form.IOnChangeListener;
import org.apache.wicket.model.IModel;
import org.apache.wicket.protocol.http.portlet.PortletRequestContext;
import org.apache.wicket.util.string.Strings;
import org.streets.eis.component.AjaxFormComponentUpdatedBehavior;
import org.streets.eis.component.ChangedNotifyType;
import org.streets.eis.component.WebResources;
import org.streets.eis.component.model.ListItem;

public abstract class ButtonedEdit extends AbstractTextComponent<ListItem> implements IOnChangeListener,IHeaderContributor{
	private static final long serialVersionUID = 1L;

	public static final String CODEID_SUFFIX = "_$Id";
	
	public ButtonedEdit(String id){
		this(id,null);
	}
	
	public ButtonedEdit(String id, IModel<ListItem> model){
		super(id,model);
		init();
	}

	
	private void init(){
		add(newButtonBahavior());
		
		if (getChangedNotifyType()==ChangedNotifyType.AJAX){
			add(new AjaxFormComponentUpdatedBehavior("onchange"){
				private static final long serialVersionUID = 1L;
				@Override
				protected CharSequence getPostData(){
					return "\""+getInputName() +	"=\" + this.value + \"&" + 
						getIdFieldId()+ "=\" + document.getElementById('"+getIdFieldMarkupId()+"').value";
				}
				@Override
				protected void onUpdate(AjaxRequestTarget target) {
					ButtonedEdit.this.onAjaxValueChanged(ButtonedEdit.this.getModelObject(),target);
				}
			});
		}
	}
	
	public void renderHead(IHeaderResponse response) {
		response.renderJavascriptReference(WebResources.Streets.Edit.BUTTONED_JS);
		String id = getMarkupId();
		String initJS = String.format("var %s=new Streets.ButtonedEdit('%s');", id,id);
		response.renderOnDomReadyJavascript(initJS);
	}
	
	protected ButtonedBehavior newButtonBahavior(){
		return new ButtonedBehavior(){
			private static final long serialVersionUID = 1L;
			@Override
			protected void onButtonClicked(AjaxRequestTarget target){
				ButtonedEdit.this.onButtonClicked(ButtonedEdit.this,target);
			}			
		};
	}

	@Override
	protected void onRender(final MarkupStream markupStream){	
		super.onRender(markupStream);
		String text = getTextValue().replace("\"", "&#34;");
		StringBuilder buffer = new StringBuilder();
		buffer.append("<span style=\"display:none\"><input type=\"hidden\" name=\"").append(getIdFieldId())
			.append("\" id=\"").append(getIdFieldMarkupId()).append("\" value=\"").append(getIdValue()).append("\" ")
			.append(" i=\"").append(getIdValue()).append("\"").append(" t=\"").append(text).append("\"")
			.append(" /></span>");

		getResponse().write(buffer);			
	}

	@Override
	protected void onComponentTag(ComponentTag tag){
		checkComponentTag(tag, "input");
		if (tag.getAttributes().containsKey("type")){
			checkComponentTagAttribute(tag, "type", "text");
		} else {
			tag.put("type", "text");
		}		
		tag.put("readonly", "readonly");
		if (isRequired()) {
			tag.put("r", "1");
		}
		tag.put("value", getModelValue());		
		tag.put("autocomplete", "off");
		
		String title = tag.getAttribute("title");
		if (!Strings.isEmpty(title)){
			tag.put("title", title);
		}
		if (getChangedNotifyType()==ChangedNotifyType.FORM){
			CharSequence url = urlFor(IOnChangeListener.INTERFACE);

			Form<?> form = findParent(Form.class);
			if (form != null){
				RequestContext rc = RequestContext.get();
				if (rc.isPortletRequest()){
					url = ((PortletRequestContext)rc).getLastEncodedPath();
				}
				tag.put("onchange", form.getJsForInterfaceUrl(url));
			} else {
				tag.put("onchange", "window.location.href='" + url +
						(url.toString().indexOf('?') > -1 ? "&amp;" : "?") + 
						getInputName() +	"=' + this.value + '&amp;" +
						getIdFieldId()+ "=' + document.getElementById('"+getIdFieldMarkupId()+"').value;");
			}
		}
		super.onComponentTag(tag);
	}

	protected String getIdFieldId(){
		return getInputName() + CODEID_SUFFIX;
	}
	
	protected String getIdFieldMarkupId(){
		return getMarkupId() + CODEID_SUFFIX;
	}	
	
	protected String getIdValue(){
		ListItem model = getModelObject();
		return model!=null?model.getId() : "";
	}
	
	protected String getTextValue(){
		ListItem model = getModelObject();
		return model!=null?model.getText() : "";
	}
	
	@Override
	public String getModelValue(){
		return getTextValue();
	}

	@Override
	protected void convertInput(){
		String id = getRequest().getParameter(getIdFieldId());
		String text = getRequest().getParameter(getInputName());
		setConvertedInput(new ListItem(id,text));
	}
		
	public void onSelectionChanged() {
		convertInput();
		updateModel();
		onValueChanged(getModelObject());
	}
	
	protected ChangedNotifyType getChangedNotifyType(){
		return ChangedNotifyType.NONE;
	}	

	public void setValue(String id,String text,AjaxRequestTarget target){
		StringBuffer js = new StringBuffer();
		
		String idField = getIdFieldMarkupId();
		String textField = getMarkupId();
		
		js.append("{var changed=").append("\"").append(id).append("\" != Wicket.$(\"").append(idField).append("\").value;")
			.append("Wicket.$(\"").append(idField).append("\").value=\"").append(id).append("\";")
			.append("Wicket.$(\"").append(textField).append("\").value=\"").append(text).append("\";")
			.append("if (changed) { Wicket.$(\"").append(textField).append("\").onchange();}")
			.append("}");
		
		target.appendJavascript(js.toString());
	}
	
	public void setValue(ListItem item,AjaxRequestTarget target){
		setValue(item.getId(),item.getText(),target);
	}
	
	public void ajaxRefresh(AjaxRequestTarget target){
		setValue(getModelObject(),target);
	}
	
	protected void onValueChanged(ListItem newValue){
	}	
	
	/** 
	 * 对于要在此方法里使用ajax更新的控件，如果是类似ButtonEdit这种会生成多个平级html dom元素的（不是单html dom根的）
	 * 要在被更新的控件的wicket-component结构上加一个WebMarkupContainer控件并更新它
	 * 否则，weicket只会替换掉html dom id为其MarkupId的Element,其他元素会重复
	 */
	protected void onAjaxValueChanged(ListItem newValue,AjaxRequestTarget target){
	}

	protected abstract void onButtonClicked(ButtonedEdit edit,AjaxRequestTarget target);
	
}
